/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "StdAfx.h"
#include "..\TextureAtlas.h"
#include <algorithm>
#include "Thread.h"

TextureAtlas* g_pTextureAtlas = NULL;

static thread::Mutex mutex;

void coreInitTextureAtlas()
{
	synchronized(mutex) {
		if (!g_pTextureAtlas) {
			g_pTextureAtlas = new TextureAtlas();
		}
	}
}

TextureAtlas* coreGetTextureAtlas()
{
	return g_pTextureAtlas;
}


TextureAtlas::TextureAtlas(void)
: m_bHalfTexel(false)
{
	m_mAtlasInfo.clear();
	m_lLoadedDefinitions.clear();
}

TextureAtlas::~TextureAtlas(void)
{
	m_mAtlasInfo.clear();
}

void Split(const std::string& str, const std::string& delim, std::vector<std::string>& output)
{
	size_t offset = 0;
    size_t delimIndex = 0;
    
    delimIndex = str.find(delim, offset);

	while (delimIndex != std::string::npos)
    {
        output.push_back(str.substr(offset, delimIndex - offset));
        offset += delimIndex - offset + delim.length();
        delimIndex = str.find(delim, offset);
    }

    output.push_back(str.substr(offset));
}

bool TextureAtlas::addAtlasDefinition(const std::string &filename)
{
	std::ifstream g_InputFile;
	int                     g_FirstLine;            // First line of .tai file w/ texture info
    int                     g_LastLine;             // Last line of .tai file w/ texture info
    int                     g_CurrentLine;          // Current line of .tai file
	m_bHalfTexel = false;
	g_InputFile.open( filename.c_str(), std::ios_base::in );

	// Error checking.
	if (!g_InputFile.is_open()) {
		//coreGetLog()->WriteError("Error opening texture atlas file: " + filename);
		return false;
	}

	// Check if this file was already loaded
	std::vector<std::string>::iterator pos = std::find(m_lLoadedDefinitions.begin(), m_lLoadedDefinitions.end(), filename);
	if (pos != m_lLoadedDefinitions.end()) {
		return false;
	}

	coreGetLog()->WriteLog("New TextureAtlas definition found: " + filename);
	m_lLoadedDefinitions.push_back(filename);

    // Skip past comments to the first line of the file with valid data.
	std::string  line;
    int     linecount = 0;
    char    ch = g_InputFile.peek();
    while ( ch == '#' || ch == '\n' )
    {
        // look on the second line for the -halftexel option
        if (++linecount == 2)
        {
			std::string word;
			std::streampos const kMark = g_InputFile.tellg();

            while (g_InputFile.peek() != '\n')
            {
                g_InputFile >> word;  
                if (word.compare("-halftexel") == 0)
                {
                    m_bHalfTexel = true;
                    break;
                }
            }
            g_InputFile.seekg( kMark );
        }
        g_InputFile.ignore( 2048, '\n' );
        ch = g_InputFile.peek();
    }

    // Save the line number the first entry.
    g_FirstLine = linecount;

    // Get/save the line number of the last entry.
    while ( g_InputFile.ignore( 2048, '\n' ) )
        ++linecount;

    g_LastLine = linecount-2;

    // Set the file pointer to the first entry.
    g_CurrentLine = g_FirstLine;
    g_InputFile.clear();    // clear eof state
	g_InputFile.seekg( 0, std::ios::beg );
    for ( int i = 0; i < g_CurrentLine; ++i)
        g_InputFile.ignore( 2048, '\n' );

	while (!g_InputFile.eof()) {
		// save file position
		//std::streampos mark = g_InputFile.tellg();
		sAtlasInfo ai;

		g_InputFile >> ai.filename;        // filename
		g_InputFile >> ai.atlasFilename;       // atlas name
		g_InputFile >> ai.atlasIdx;      // texture atlas index
		g_InputFile.get( ch );          // comma
		g_InputFile >> ai.atlasType;       // atlas type
		g_InputFile >> ai.offset.x;         // woffset
		g_InputFile.get( ch );          // comma
		g_InputFile >> ai.offset.y;         // hoffset
		g_InputFile.get( ch );          // read comma
		g_InputFile >> ai.offset.z;           // slice (if volume texture or cubemap
		g_InputFile.get( ch );          // read comma
		g_InputFile >> ai.width;           // width
		g_InputFile.get( ch );          // read comma
		g_InputFile >> ai.height;          // height

		ai.atlasFilename = ai.atlasFilename.substr(0, ai.atlasFilename.size()-1);
		ai.atlasType = ai.atlasType.substr(0, ai.atlasType.size()-1);
		ai.halfTexel = m_bHalfTexel;
		if (ai.filename.compare("") != 0)
			m_mAtlasInfo[ai.filename] = ai;
		// restore file position
		//g_InputFile.seekg( mark );
	}
	g_InputFile.close();
	return true;
}

bool TextureAtlas::hasDefinition(const std::string &filename)
{
	// Get the correct substring 
	// Look if in atlas with the /data/textures/ part killed
	if (m_mAtlasInfo.find(filename.substr(15)) != m_mAtlasInfo.end()) {
		return true;
	}
	return false;
}

sAtlasInfo TextureAtlas::getAtlasInfo(const std::string &realname)
{	
	/// Kill the /data/textures/ part
	std::string substr = realname.substr(15);
	// Look if in atlas
	if (m_mAtlasInfo.find(substr) != m_mAtlasInfo.end()) {
		return m_mAtlasInfo[substr];
	}
	sAtlasInfo ai;
	memset(&ai, 0, sizeof(sAtlasInfo));
	return ai;
}